```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>深入解析Java ClassLoader机制 | 技术小馆</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', 'Noto Serif SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            background-color: #f8fafc;
            color: #1e293b;
            line-height: 1.6;
        }
        .hero-gradient {
            background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #d946ef 100%);
        }
        .code-block {
            background-color: #1e293b;
            color: #e2e8f0;
            border-radius: 0.5rem;
            font-family: 'Courier New', Courier, monospace;
        }
        .hover-scale {
            transition: transform 0.2s ease-in-out;
        }
        .hover-scale:hover {
            transform: translateY(-2px);
        }
        .shadow-soft {
            box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
        }
        .shadow-hard {
            box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
        }
        .section-divider {
            border-bottom: 1px solid #e2e8f0;
        }
        .highlight {
            position: relative;
        }
        .highlight::after {
            content: '';
            position: absolute;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 10px;
            background-color: rgba(124, 58, 237, 0.2);
            z-index: -1;
            transform: scaleX(1.05);
        }
    </style>
</head>
<body class="antialiased">
    <!-- Hero Section -->
    <div class="hero-gradient text-white py-20 px-4 sm:px-6 lg:px-8">
        <div class="max-w-4xl mx-auto text-center">
            <div class="inline-flex items-center mb-4 px-4 py-2 rounded-full bg-white bg-opacity-20">
                <i class="fas fa-microchip mr-2"></i>
                <span class="text-sm font-medium">Java核心技术</span>
            </div>
            <h1 class="text-4xl md:text-5xl font-bold mb-6">深入解析Java ClassLoader机制</h1>
            <p class="text-xl md:text-2xl font-light max-w-3xl mx-auto opacity-90">
                Java虚拟机的"搬运工"——揭秘类加载器的核心原理与实战应用
            </p>
            <div class="mt-10 flex justify-center space-x-4">
                <a href="#basics" class="px-6 py-3 bg-white text-indigo-600 font-medium rounded-full hover:bg-opacity-90 transition-all hover:shadow-lg">
                    <i class="fas fa-book-reader mr-2"></i>开始阅读
                </a>
                <a href="#applications" class="px-6 py-3 bg-transparent border-2 border-white text-white font-medium rounded-full hover:bg-white hover:bg-opacity-10 transition-all">
                    <i class="fas fa-laptop-code mr-2"></i>实战应用
                </a>
            </div>
        </div>
    </div>

    <!-- Main Content -->
    <div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
        <!-- Introduction -->
        <div class="mb-16">
            <p class="text-lg md:text-xl leading-relaxed text-slate-700">
                在Java开发中，ClassLoader（类加载器）是一个核心而又常被忽视的组件。它就像是Java虚拟机的"搬运工"，负责将字节码文件加载到JVM中，是Java程序运行的基础设施。无论是Spring Boot的自动配置、热部署功能，还是OSGi的模块化系统，甚至是各种框架的插件机制，都离不开ClassLoader的支持。
            </p>
        </div>

        <!-- Table of Contents -->
        <div class="bg-white rounded-xl shadow-soft p-6 mb-16">
            <h2 class="text-xl font-bold mb-4 text-indigo-600 flex items-center">
                <i class="fas fa-list-ol mr-2"></i> 目录导航
            </h2>
            <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
                <a href="#1" class="hover-scale block p-4 border border-gray-100 rounded-lg hover:border-indigo-300 hover:bg-indigo-50 transition-all">
                    <h3 class="font-medium text-indigo-600 mb-2">1. ClassLoader基础</h3>
                    <p class="text-sm text-gray-600">概念、层次结构与加载过程</p>
                </a>
                <a href="#2" class="hover-scale block p-4 border border-gray-100 rounded-lg hover:border-indigo-300 hover:bg-indigo-50 transition-all">
                    <h3 class="font-medium text-indigo-600 mb-2">2. 源码解析与工作原理</h3>
                    <p class="text-sm text-gray-600">核心方法、双亲委派模型</p>
                </a>
                <a href="#3" class="hover-scale block p-4 border border-gray-100 rounded-lg hover:border-indigo-300 hover:bg-indigo-50 transition-all">
                    <h3 class="font-medium text-indigo-600 mb-2">3. 实际项目应用</h3>
                    <p class="text-sm text-gray-600">热部署、Spring Boot、Tomcat</p>
                </a>
                <a href="#4" class="hover-scale block p-4 border border-gray-100 rounded-lg hover:border-indigo-300 hover:bg-indigo-50 transition-all">
                    <h3 class="font-medium text-indigo-600 mb-2">4. 面试高频问题</h3>
                    <p class="text-sm text-gray-600">常见问题解析与最佳实践</p>
                </a>
            </div>
        </div>

        <!-- Section 1 -->
        <div id="1" class="mb-20">
            <div class="flex items-center mb-8">
                <div class="bg-indigo-100 w-12 h-12 rounded-full flex items-center justify-center mr-4">
                    <span class="text-indigo-600 text-xl font-bold">1</span>
                </div>
                <h2 class="text-2xl md:text-3xl font-bold text-gray-800">ClassLoader基础</h2>
            </div>

            <!-- Subsection 1.1 -->
            <div id="1.1" class="mb-12">
                <div class="flex items-center mb-6">
                    <div class="w-8 h-8 bg-indigo-50 rounded-full flex items-center justify-center mr-3">
                        <span class="text-indigo-600 text-sm font-bold">1.1</span>
                    </div>
                    <h3 class="text-xl font-semibold text-gray-800">什么是ClassLoader？</h3>
                </div>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        ClassLoader是Java虚拟机的重要组成部分，它主要负责将类的字节码（.class文件）加载到JVM内存中，并生成对应的Class对象。简单来说，当你在代码中首次使用某个类时，JVM会通过ClassLoader将这个类加载到内存中。
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-6 overflow-x-auto">
                        <pre><code class="text-sm language-java">// 获取当前线程的上下文类加载器
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();

// 使用类加载器加载资源
URL resource = contextClassLoader.getResource("config.properties");

// 获取一个类的类加载器
ClassLoader classLoader = MyClass.class.getClassLoader();</code></pre>
                    </div>
                </div>
            </div>

            <!-- Subsection 1.2 -->
            <div id="1.2" class="mb-12">
                <div class="flex items-center mb-6">
                    <div class="w-8 h-8 bg-indigo-50 rounded-full flex items-center justify-center mr-3">
                        <span class="text-indigo-600 text-sm font-bold">1.2</span>
                    </div>
                    <h3 class="text-xl font-semibold text-gray-800">ClassLoader的层次结构</h3>
                </div>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        Java中的ClassLoader采用了父委托模型（Parent Delegation Model），形成了一个层次结构：
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-4 overflow-x-auto">
                        <pre><code class="text-sm language-java">// 获取不同层次的类加载器
ClassLoader appClassLoader = ClassLoader.getSystemClassLoader(); // 应用类加载器
ClassLoader extClassLoader = appClassLoader.getParent(); // 扩展类加载器
ClassLoader bootstrapClassLoader = extClassLoader.getParent(); // 启动类加载器（返回null）

System.out.println("应用类加载器: " + appClassLoader);
System.out.println("扩展类加载器: " + extClassLoader);
System.out.println("启动类加载器: " + bootstrapClassLoader);</code></pre>
                    </div>
                    
                    <p class="mb-4 text-gray-700">
                        输出结果类似于：
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-4 overflow-x-auto">
                        <pre><code class="text-sm">应用类加载器: sun.misc.Launcher$AppClassLoader@18b4aac2
扩展类加载器: sun.misc.Launcher$ExtClassLoader@1b6d3586
启动类加载器: null</code></pre>
                    </div>
                    
                    <p class="mb-4 text-gray-700">
                        这三个类加载器各司其职：
                    </p>
                    
                    <div class="bg-blue-50 border-l-4 border-blue-400 p-4 mb-6">
                        <div class="flex">
                            <div class="flex-shrink-0">
                                <i class="fas fa-info-circle text-blue-500"></i>
                            </div>
                            <div class="ml-3">
                                <ol class="list-decimal pl-5 space-y-1">
                                    <li><strong>启动类加载器（Bootstrap ClassLoader）</strong>：负责加载Java核心类库，如rt.jar、resources.jar等</li>
                                    <li><strong>扩展类加载器（Extension ClassLoader）</strong>：负责加载Java扩展类库，位于JRE的lib/ext目录</li>
                                    <li><strong>应用类加载器（Application ClassLoader）</strong>：负责加载应用程序classpath下的类</li>
                                </ol>
                            </div>
                        </div>
                    </div>
                    
                    <!-- Mermaid Diagram -->
                    <div class="bg-white p-6 rounded-lg shadow-soft mb-6">
                        <div class="mermaid">
                            graph TD
                                A[启动类加载器\nBootstrap ClassLoader] -->|父加载器| B[扩展类加载器\nExtension ClassLoader]
                                B -->|父加载器| C[应用类加载器\nApplication ClassLoader]
                                C -->|父加载器| D[自定义类加载器]
                        </div>
                    </div>
                </div>
            </div>

            <!-- Subsection 1.3 -->
            <div id="1.3">
                <div class="flex items-center mb-6">
                    <div class="w-8 h-8 bg-indigo-50 rounded-full flex items-center justify-center mr-3">
                        <span class="text-indigo-600 text-sm font-bold">1.3</span>
                    </div>
                    <h3 class="text-xl font-semibold text-gray-800">类加载的过程</h3>
                </div>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        类加载过程分为三个主要步骤：
                    </p>
                    
                    <div class="bg-blue-50 border-l-4 border-blue-400 p-4 mb-6">
                        <div class="flex">
                            <div class="flex-shrink-0">
                                <i class="fas fa-list-ol text-blue-500"></i>
                            </div>
                            <div class="ml-3">
                                <ol class="list-decimal pl-5 space-y-1">
                                    <li><strong>加载（Loading）</strong>：查找并加载类的二进制数据</li>
                                    <li><strong>链接（Linking）</strong>：
                                        <ul class="list-disc pl-5 mt-1">
                                            <li>验证（Verification）：确保类的二进制数据符合JVM规范</li>
                                            <li>准备（Preparation）：为类的静态变量分配内存并设置默认值</li>
                                            <li>解析（Resolution）：将符号引用转换为直接引用</li>
                                        </ul>
                                    </li>
                                    <li><strong>初始化（Initialization）</strong>：执行类的静态初始化代码</li>
                                </ol>
                            </div>
                        </div>
                    </div>
                    
                    <div class="code-block p-4 rounded-lg mb-4 overflow-x-auto">
                        <pre><code class="text-sm language-java">public class ClassLoadingDemo {
    // 静态变量，在准备阶段分配内存并赋默认值（0）
    static int value = 10; // 在初始化阶段赋值为10
    
    // 静态代码块，在初始化阶段执行
    static {
        System.out.println("ClassLoadingDemo静态代码块执行");
        value = 20;
    }
    
    public static void main(String[] args) {
        System.out.println("value = " + value);
    }
}</code></pre>
                    </div>
                    
                    <p class="mb-4 text-gray-700">
                        输出结果：
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-6 overflow-x-auto">
                        <pre><code class="text-sm">ClassLoadingDemo静态代码块执行
value = 20</code></pre>
                    </div>
                    
                    <!-- Timeline Visualization -->
                    <div class="bg-white p-6 rounded-lg shadow-soft">
                        <h4 class="font-medium text-gray-800 mb-4 flex items-center">
                            <i class="fas fa-project-diagram mr-2 text-indigo-500"></i> 类加载过程时间线
                        </h4>
                        <div class="mermaid">
                            gantt
                                title 类加载过程
                                dateFormat  HH:mm:ss
                                axisFormat %S秒
                                section 加载
                                加载.class文件        :a1, 00:00:00, 1s
                                section 链接
                                验证                 :a2, after a1, 1s
                                准备                 :a3, after a2, 1s
                                解析                 :a4, after a3, 1s
                                section 初始化
                                执行静态代码块        :a5, after a4, 1s
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Section 2 -->
        <div id="2" class="mb-20">
            <div class="flex items-center mb-8">
                <div class="bg-indigo-100 w-12 h-12 rounded-full flex items-center justify-center mr-4">
                    <span class="text-indigo-600 text-xl font-bold">2</span>
                </div>
                <h2 class="text-2xl md:text-3xl font-bold text-gray-800">源码解析与工作原理</h2>
            </div>

            <!-- Subsection 2.1 -->
            <div id="2.1" class="mb-12">
                <div class="flex items-center mb-6">
                    <div class="w-8 h-8 bg-indigo-50 rounded-full flex items-center justify-center mr-3">
                        <span class="text-indigo-600 text-sm font-bold">2.1</span>
                    </div>
                    <h3 class="text-xl font-semibold text-gray-800">ClassLoader的核心方法</h3>
                </div>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        ClassLoader是一个抽象类，它定义了类加载的核心方法：
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-6 overflow-x-auto">
                        <pre><code class="text-sm language-java">public abstract class ClassLoader {
    // 加载指定名称的类
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }
    
    // 实际的类加载逻辑
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            // 首先检查类是否已经加载
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    // 委托父类加载器加载
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        // 如果没有父加载器，使用启动类加载器
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // 父加载器无法加载，记录异常
                }
                
                if (c == null) {
                    // 父加载器无法加载，尝试自己加载
                    c = findClass(name);
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }
    
    // 由子类实现的查找类的方法
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        throw new ClassNotFoundException(name);
    }
    
    // 其他方法...
}</code></pre>
                    </div>
                    
                    <p class="mb-4 text-gray-700">
                        这段源码展示了类加载的核心逻辑和父委托模型的实现：
                    </p>
                    
                    <ul class="list-disc pl-5 space-y-2 mb-6 text-gray-700">
                        <li>首先检查类是否已经加载</li>
                        <li>如果未加载，委托父加载器加载</li>
                        <li>如果父加载器无法加载，则调用自己的findClass方法加载</li>
                    </ul>
                </div>
            </div>

            <!-- Subsection 2.2 -->
            <div id="2.2" class="mb-12">
                <div class="flex items-center mb-6">
                    <div class="w-8 h-8 bg-indigo-50 rounded-full flex items-center justify-center mr-3">
                        <span class="text-indigo-600 text-sm font-bold">2.2</span>
                    </div>
                    <h3 class="text-xl font-semibold text-gray-800">双亲委派模型的工作原理</h3>
                </div>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        双亲委派模型的核心思想是：当一个类加载器收到类加载请求时，它首先将请求委派给父加载器，依次向上。只有当父加载器无法加载时，子加载器才会尝试自己加载。
                    </p>
                    
                    <p class="mb-4 text-gray-700">
                        这种机制有两个重要优势：
                    </p>
                    
                    <div class="bg-blue-50 border-l-4 border-blue-400 p-4 mb-6">
                        <div class="flex">
                            <div class="flex-shrink-0">
                                <i class="fas fa-check-circle text-blue-500"></i>
                            </div>
                            <div class="ml-3">
                                <ol class="list-decimal pl-5 space-y-1">
                                    <li><strong>确保Java核心类的安全性</strong>：防止用户自定义的类替换Java核心类</li>
                                    <li><strong>避免类的重复加载</strong>：同一个类只会被加载一次</li>
                                </ol>
                            </div>
                        </div>
                    </div>
                    
                    <div class="code-block p-4 rounded-lg mb-4 overflow-x-auto">
                        <pre><code class="text-sm language-java">// 演示双亲委派模型
public class ParentDelegationDemo {
    public static void main(String[] args) throws Exception {
        // 创建自定义类加载器
        ClassLoader myLoader = new ClassLoader(ClassLoader.getSystemClassLoader()) {
            @Override
            protected Class<?> findClass(String name) throws ClassNotFoundException {
                // 自定义类加载逻辑
                System.out.println("自定义类加载器尝试加载: " + name);
                throw new ClassNotFoundException(name);
            }
        };
        
        // 尝试加载java.lang.String类
        try {
            Class<?> clazz = myLoader.loadClass("java.lang.String");
            System.out.println("String类的加载器: " + clazz.getClassLoader());
        } catch (ClassNotFoundException e) {
            System.out.println("加载失败: " + e.getMessage());
        }
    }
}</code></pre>
                    </div>
                    
                    <p class="mb-4 text-gray-700">
                        输出结果：
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-6 overflow-x-auto">
                        <pre><code class="text-sm">String类的加载器: null</code></pre>
                    </div>
                    
                    <p class="mb-4 text-gray-700">
                        这里String类由启动类加载器加载，而不是我们的自定义加载器，这正是双亲委派模型的效果。
                    </p>
                    
                    <!-- Mermaid Sequence Diagram -->
                    <div class="bg-white p-6 rounded-lg shadow-soft">
                        <div class="mermaid">
                            sequenceDiagram
                                participant App as 应用类加载器
                                participant Ext as 扩展类加载器
                                participant Boot as 启动类加载器
                                App->>Ext: 加载类请求
                                Ext->>Boot: 加载类请求
                                Boot-->>Ext: 加载失败/成功
                                Ext-->>App: 加载失败
                                App->>App: 尝试自己加载
                        </div>
                    </div>
                </div>
            </div>

            <!-- Subsection 2.3 -->
            <div id="2.3">
                <div class="flex items-center mb-6">
                    <div class="w-8 h-8 bg-indigo-50 rounded-full flex items-center justify-center mr-3">
                        <span class="text-indigo-600 text-sm font-bold">2.3</span>
                    </div>
                    <h3 class="text-xl font-semibold text-gray-800">打破双亲委派模型</h3>
                </div>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        在某些场景下，我们需要打破双亲委派模型，例如SPI（Service Provider Interface）机制、OSGi等。实现方式有两种：
                    </p>
                    
                    <div class="grid md:grid-cols-2 gap-6 mb-6">
                        <!-- Option 1 -->
                        <div class="bg-white p-6 rounded-lg shadow-soft hover:shadow-hard transition-shadow">
                            <h4 class="font-medium text-indigo-600 mb-3 flex items-center">
                                <i class="fas fa-code-branch mr-2"></i> 1. 重写loadClass方法
                            </h4>
                            <p class="text-gray-700 mb-4">
                                直接修改类加载的逻辑
                            </p>
                            <div class="code-block p-4 rounded-lg overflow-x-auto">
                                <pre><code class="text-xs language-java">public class NonDelegatingClassLoader extends ClassLoader {
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        // 检查类是否已加载
        Class<?> loadedClass = findLoadedClass(name);
        if (loadedClass != null) return loadedClass;
        
        // 对于java.*和javax.*包下的类，仍然委托给父加载器
        if (name.startsWith("java.") || name.startsWith("javax.")) {
            return super.loadClass(name);
        }
        
        // 其他类尝试自己加载
        try {
            return findClass(name);
        } catch (ClassNotFoundException e) {
            // 如果自己无法加载，再委托给父加载器
            return super.loadClass(name);
        }
    }
}</code></pre>
                            </div>
                        </div>
                        
                        <!-- Option 2 -->
                        <div class="bg-white p-6 rounded-lg shadow-soft hover:shadow-hard transition-shadow">
                            <h4 class="font-medium text-indigo-600 mb-3 flex items-center">
                                <i class="fas fa-exchange-alt mr-2"></i> 2. 使用线程上下文类加载器
                            </h4>
                            <p class="text-gray-700 mb-4">
                                Java提供了Thread.setContextClassLoader()方法，可以在运行时动态修改类加载器
                            </p>
                            <div class="code-block p-4 rounded-lg overflow-x-auto">
                                <pre><code class="text-xs language-java">// 保存当前线程的上下文类加载器
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
try {
    // 设置新的上下文类加载器
    Thread.currentThread().setContextClassLoader(myClassLoader);
    
    // 使用ServiceLoader加载服务实现
    ServiceLoader&lt;MyService&gt; serviceLoader = ServiceLoader.load(MyService.class);
    for (MyService service : serviceLoader) {
        service.doSomething();
    }
} finally {
    // 恢复原来的上下文类加载器
    Thread.currentThread().setContextClassLoader(oldClassLoader);
}</code></pre>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Section 3 -->
        <div id="3" class="mb-20">
            <div class="flex items-center mb-8">
                <div class="bg-indigo-100 w-12 h-12 rounded-full flex items-center justify-center mr-4">
                    <span class="text-indigo-600 text-xl font-bold">3</span>
                </div>
                <h2 class="text-2xl md:text-3xl font-bold text-gray-800">ClassLoader在实际项目中的应用</h2>
            </div>

            <!-- Subsection 3.1 -->
            <div id="3.1" class="mb-12">
                <div class="flex items-center mb-6">
                    <div class="w-8 h-8 bg-indigo-50 rounded-full flex items-center justify-center mr-3">
                        <span class="text-indigo-600 text-sm font-bold">3.1</span>
                    </div>
                    <h3 class="text-xl font-semibold text-gray-800">自定义ClassLoader实现热部署</h3>
                </div>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        在开发环境中，我们经常需要热部署功能，避免重启应用。自定义ClassLoader可以实现这一功能：
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-4 overflow-x-auto">
                        <pre><code class="text-sm language-java">public class HotSwapClassLoader extends ClassLoader {
    private String classPath;
    private Map&lt;String, Long&gt; loadTimeMap = new HashMap&lt;&gt;();
    
    public HotSwapClassLoader(String classPath) {
        this.classPath = classPath;
    }
    
    @Override
    protected Class&lt;?&gt; findClass(String name) throws ClassNotFoundException {
        String fileName = classPath + File.separator + 
                          name.replace('.', File.separatorChar) + ".class";
        File file = new File(fileName);
        
        if (!file.exists()) {
            throw new ClassNotFoundException(name);
        }
        
        // 检查类文件是否已更新
        long lastModified = file.lastModified();
        if (loadTimeMap.containsKey(name) &amp;&amp; loadTimeMap.get(name) == lastModified) {
            // 类文件未更新，使用已加载的类
            Class&lt;?&gt; loadedClass = findLoadedClass(name);
            if (loadedClass != null) {
                return loadedClass;
            }
        }
        
        // 加载类文件
        try (FileInputStream fis = new FileInputStream(file);
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesRead);
            }
            byte[] classData = baos.toByteArray();
            
            // 记录加载时间
            loadTimeMap.put(name, lastModified);
            
            // 定义类
            return defineClass(name, classData, 0, classData.length);
        } catch (IOException e) {
            throw new ClassNotFoundException("Could not load class: " + name, e);
        }
    }
    
    // 清除已加载的类，强制重新加载
    public void clearCache() {
        loadTimeMap.clear();
    }
}</code></pre>
                    </div>
                    
                    <p class="mb-4 text-gray-700">
                        使用示例：
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-6 overflow-x-auto">
                        <pre><code class="text-sm language-java">public class HotSwapDemo {
    public static void main(String[] args) throws Exception {
        String classPath = "D:/hotswap";
        HotSwapClassLoader loader = new HotSwapClassLoader(classPath);
        
        while (true) {
            // 每隔5秒尝试重新加载类
            try {
                Class&lt;?&gt; clazz = loader.loadClass("com.example.MyService");
                Object instance = clazz.newInstance();
                Method method = clazz.getMethod("process");
                method.invoke(instance);
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            Thread.sleep(5000);
            // 清除缓存，强制重新加载
            loader.clearCache();
        }
    }
}</code></pre>
                    </div>
                </div>
            </div>

            <!-- Subsection 3.2 -->
            <div id="3.2" class="mb-12">
                <div class="flex items-center mb-6">
                    <div class="w-8 h-8 bg-indigo-50 rounded-full flex items-center justify-center mr-3">
                        <span class="text-indigo-600 text-sm font-bold">3.2</span>
                    </div>
                    <h3 class="text-xl font-semibold text-gray-800">Spring Boot中的类加载机制</h3>
                </div>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        Spring Boot使用了复杂的类加载机制，特别是在可执行JAR和自动配置方面：
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-4 overflow-x-auto">
                        <pre><code class="text-sm language-java">// Spring Boot的LaunchedURLClassLoader简化版
public class LaunchedURLClassLoader extends URLClassLoader {
    
    public LaunchedURLClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
    }
    
    @Override
    protected Class&lt;?&gt; loadClass(String name, boolean resolve) throws ClassNotFoundException {
        try {
            // 尝试从已加载的类中查找
            Class&lt;?&gt; loadedClass = findLoadedClass(name);
            if (loadedClass != null) {
                return resolveClass(loadedClass, resolve);
            }
            
            // 对于特定包，优先自己加载
            if (isExcluded(name)) {
                Class&lt;?&gt; found = findClass(name);
                return resolveClass(found, resolve);
            }
            
            // 其他情况委托给父加载器
            try {
                Class&lt;?&gt; found = getParent().loadClass(name);
                return resolveClass(found, resolve);
            } catch (ClassNotFoundException ex) {
                // 父加载器无法加载，尝试自己加载
            }
            
            Class&lt;?&gt; found = findClass(name);
            return resolveClass(found, resolve);
        } catch (ClassNotFoundException ex) {
            throw ex;
        }
    }
    
    private boolean isExcluded(String name) {
        // 判断是否为需要特殊处理的包
        return name.startsWith("org.springframework.boot.");
    }
    
    private Class&lt;?&gt; resolveClass(Class&lt;?&gt; clazz, boolean resolve) {
        if (resolve) {
            resolveClass(clazz);
        }
        return clazz;
    }
}</code></pre>
                    </div>
                    
                    <p class="mb-4 text-gray-700">
                        Spring Boot的类加载器在某些情况下会打破双亲委派模型，以支持特定的功能，如Fat JAR（将依赖打包到一个JAR中）和自动配置。
                    </p>
                </div>
            </div>

            <!-- Subsection 3.3 -->
            <div id="3.3">
                <div class="flex items-center mb-6">
                    <div class="w-8 h-8 bg-indigo-50 rounded-full flex items-center justify-center mr-3">
                        <span class="text-indigo-600 text-sm font-bold">3.3</span>
                    </div>
                    <h3 class="text-xl font-semibold text-gray-800">Tomcat的类加载机制</h3>
                </div>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        Tomcat使用了复杂的多级类加载器结构，以支持Web应用的隔离和热部署：
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-4 overflow-x-auto">
                        <pre><code class="text-sm language-java">// Tomcat的WebappClassLoader简化版
public class WebappClassLoader extends URLClassLoader {
    
    private final ClassLoader javaseClassLoader;
    
    public WebappClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
        ClassLoader systemClassLoader = getSystemClassLoader();
        if (systemClassLoader == null) {
            this.javaseClassLoader = null;
        } else {
            this.javaseClassLoader = systemClassLoader.getParent();
        }
    }
    
    @Override
    public Class&lt;?&gt; loadClass(String name, boolean resolve) throws ClassNotFoundException {
        // 检查JVM缓存的类
        Class&lt;?&gt; clazz = findLoadedClass(name);
        if (clazz != null) {
            return clazz;
        }
        
        // 检查是否为Java SE类
        if (name.startsWith("java.") || name.startsWith("javax.")) {
            try {
                if (javaseClassLoader != null) {
                    clazz = javaseClassLoader.loadClass(name);
                    return clazz;
                }
            } catch (ClassNotFoundException e) {
                // 忽略异常，继续尝试其他加载器
            }
        }
        
        // 检查是否为Servlet API类
        if (name.startsWith("javax.servlet.")) {
            try {
                clazz = getParent().loadClass(name);
                return clazz;
            } catch (ClassNotFoundException e) {
                // 忽略异常，继续尝试其他加载器
            }
        }
        
        // 尝试自己加载
        try {
            clazz = findClass(name);
            return clazz;
        } catch (ClassNotFoundException e) {
            // 忽略异常，继续尝试父加载器
        }
        
        // 最后尝试父加载器
        clazz = getParent().loadClass(name);
        return clazz;
    }
}</code></pre>
                    </div>
                    
                    <p class="mb-4 text-gray-700">
                        Tomcat的类加载器结构设计目标是：
                    </p>
                    
                    <ul class="list-disc pl-5 space-y-2 mb-6 text-gray-700">
                        <li>不同Web应用之间的类隔离</li>
                        <li>Web应用与Tomcat本身的类隔离</li>
                        <li>支持Web应用的热部署和热更新</li>
                    </ul>
                    
                    <!-- Mermaid Diagram -->
                    <div class="bg-white p-6 rounded-lg shadow-soft">
                        <div class="mermaid">
                            graph TD
                                Bootstrap[Bootstrap ClassLoader\nJava核心库]
                                Ext[Extension ClassLoader\nJRE扩展库]
                                System[System ClassLoader\n应用类路径]
                                Common[Common ClassLoader\nTomcat共享类]
                                WebApp1[WebApp1 ClassLoader\nWeb应用1]
                                WebApp2[WebApp2 ClassLoader\nWeb应用2]
                                
                                Bootstrap --> Ext
                                Ext --> System
                                System --> Common
                                Common --> WebApp1
                                Common --> WebApp2
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Section 4 -->
        <div id="4" class="mb-20">
            <div class="flex items-center mb-8">
                <div class="bg-indigo-100 w-12 h-12 rounded-full flex items-center justify-center mr-4">
                    <span class="text-indigo-600 text-xl font-bold">4</span>
                </div>
                <h2 class="text-2xl md:text-3xl font-bold text-gray-800">ClassLoader项目中应用</h2>
            </div>

            <!-- Subsection 4.1 -->
            <div id="4.1" class="mb-12">
                <div class="flex items-center mb-6">
                    <div class="w-8 h-8 bg-indigo-50 rounded-full flex items-center justify-center mr-3">
                        <span class="text-indigo-600 text-sm font-bold">4.1</span>
                    </div>
                    <h3 class="text-xl font-semibold text-gray-800">ClassNotFoundException vs NoClassDefFoundError</h3>
                </div>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        这两个异常经常让开发者困惑，它们的区别在于：
                    </p>
                    
                    <div class="grid md:grid-cols-2 gap-6 mb-6">
                        <div class="bg-red-50 border-l-4 border-red-400 p-4">
                            <h4 class="font-medium text-red-600 mb-2 flex items-center">
                                <i class="fas fa-exclamation-circle mr-2"></i> ClassNotFoundException
                            </h4>
                            <p class="text-gray-700">
                                当尝试通过反射加载类时，找不到类的定义
                            </p>
                            <div class="code-block p-4 rounded-lg mt-3 overflow-x-auto">
                                <pre><code class="text-xs language-java">try {
    Class.forName("com.example.NonExistentClass");
} catch (ClassNotFoundException e) {
    System.out.println("ClassNotFoundException: " + e.getMessage());
}</code></pre>
                            </div>
                        </div>
                        
                        <div class="bg-orange-50 border-l-4 border-orange-400 p-4">
                            <h4 class="font-medium text-orange-600 mb-2 flex items-center">
                                <i class="fas fa-exclamation-triangle mr-2"></i> NoClassDefFoundError
                            </h4>
                            <p class="text-gray-700">
                                当JVM或ClassLoader尝试加载类的定义时，找不到类的定义文件
                            </p>
                            <div class="code-block p-4 rounded-lg mt-3 overflow-x-auto">
                                <pre><code class="text-xs language-java">public class ErrorDemo {
    // 引用一个不存在的类
    static MissingClass obj;
    
    public static void main(String[] args) {
        try {
            // 访问静态字段会触发类加载
            System.out.println(obj);
        } catch (NoClassDefFoundError e) {
            System.out.println("NoClassDefFoundError: " + e.getMessage());
        }
    }
}</code></pre>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Subsection 4.2 -->
            <div id="4.2" class="mb-12">
                <div class="flex items-center mb-6">
                    <div class="w-8 h-8 bg-indigo-50 rounded-full flex items-center justify-center mr-3">
                        <span class="text-indigo-600 text-sm font-bold">4.2</span>
                    </div>
                    <h3 class="text-xl font-semibold text-gray-800">类加载器内存泄漏问题</h3>
                </div>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        类加载器可能导致内存泄漏，特别是在动态创建类加载器的场景：
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-4 overflow-x-auto">
                        <pre><code class="text-sm language-java">public class ClassLoaderLeakDemo {
    public static void main(String[] args) throws Exception {
        List&lt;ClassLoader&gt; loaders = new ArrayList&lt;&gt;();
        
        for (int i = 0; i &lt; 1000; i++) {
            // 创建大量类加载器
            URL[] urls = new URL[] { new URL("file:/path/to/classes/") };
            URLClassLoader loader = new URLClassLoader(urls);
            
            // 加载类
            Class&lt;?&gt; clazz = loader.loadClass("com.example.LargeClass");
            Object instance = clazz.newInstance();
            
            // 保持对类加载器的引用，防止GC
            loaders.add(loader);
            
            if (i % 100 == 0) {
                System.out.println("Created " + i + " classloaders");
                System.gc();
                Thread.sleep(100);
            }
        }
    }
}</code></pre>
                    </div>
                    
                    <p class="mb-4 text-gray-700">
                        最佳实践：
                    </p>
                    
                    <div class="bg-blue-50 border-l-4 border-blue-400 p-4 mb-6">
                        <div class="flex">
                            <div class="flex-shrink-0">
                                <i class="fas fa-lightbulb text-blue-500"></i>
                            </div>
                            <div class="ml-3">
                                <ol class="list-decimal pl-5 space-y-1">
                                    <li>不要创建过多的类加载器</li>
                                    <li>使用完类加载器后，清除所有引用，允许GC回收</li>
                                    <li>考虑使用弱引用（WeakReference）存储类加载器</li>
                                </ol>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Subsection 4.3 -->
            <div id="4.3">
                <div class="flex items-center mb-6">
                    <div class="w-8 h-8 bg-indigo-50 rounded-full flex items-center justify-center mr-3">
                        <span class="text-indigo-600 text-sm font-bold">4.3</span>
                    </div>
                    <h3 class="text-xl font-semibold text-gray-800">线程上下文类加载器的正确使用</h3>
                </div>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        线程上下文类加载器是一种打破双亲委派模型的方式，但使用不当会导致问题：
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-4 overflow-x-auto">
                        <pre><code class="text-sm language-java">public class ContextClassLoaderDemo {
    public static void main(String[] args) {
        // 保存原始上下文类加载器
        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
        
        try {
            // 设置自定义类加载器
            ClassLoader customClassLoader = new URLClassLoader(new URL[] {
                new URL("file:/path/to/classes/")
            });
            Thread.currentThread().setContextClassLoader(customClassLoader);
            
            // 使用上下文类加载器加载资源
            URL resource = Thread.currentThread().getContextClassLoader()
                                .getResource("config.properties");
            System.out.println("Resource: " + resource);
            
            // 使用ServiceLoader（内部使用上下文类加载器）
            ServiceLoader&lt;MyService&gt; serviceLoader = ServiceLoader.load(MyService.class);
            for (MyService service : serviceLoader) {
                service.doSomething();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 恢复原始上下文类加载器
            Thread.currentThread().setContextClassLoader(originalClassLoader);
        }
    }
}</code></pre>
                    </div>
                    
                    <p class="mb-4 text-gray-700">
                        最佳实践：
                    </p>
                    
                    <div class="bg-blue-50 border-l-4 border-blue-400 p-4">
                        <div class="flex">
                            <div class="flex-shrink-0">
                                <i class="fas fa-check-circle text-blue-500"></i>
                            </div>
                            <div class="ml-3">
                                <ol class="list-decimal pl-5 space-y-1">
                                    <li>使用try-finally结构，确保恢复原始类加载器</li>
                                    <li>不要在全局范围内修改上下文类加载器</li>
                                    <li>记录类加载器的变更，便于调试</li>
                                </ol>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Section 5 -->
        <div id="5" class="mb-20">
            <div class="flex items-center mb-8">
                <div class="bg-indigo-100 w-12 h-12 rounded-full flex items-center justify-center mr-4">
                    <span class="text-indigo-600 text-xl font-bold">5</span>
                </div>
                <h2 class="text-2xl md:text-3xl font-bold text-gray-800">面试中的ClassLoader高频问题</h2>
            </div>

            <!-- Question 1 -->
            <div class="mb-12 bg-white rounded-xl shadow-soft p-6">
                <h3 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
                    <span class="bg-indigo-600 text-white w-8 h-8 rounded-full flex items-center justify-center mr-3">1</span>
                    什么是双亲委派模型？为什么需要它？
                </h3>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        <span class="font-medium text-indigo-600">答：</span>双亲委派模型是Java类加载器的工作机制，它要求除了顶层的启动类加载器外，其他类加载器都应该有自己的父加载器。当一个类加载器收到类加载请求时，它首先委托父加载器加载，只有当父加载器无法加载时，才尝试自己加载。
                    </p>
                    
                    <p class="mb-4 text-gray-700">
                        双亲委派模型的好处：
                    </p>
                    
                    <ul class="list-disc pl-5 space-y-2 mb-4 text-gray-700">
                        <li>确保Java核心类的安全性：防止用户自定义的类替换Java核心类</li>
                        <li>避免类的重复加载：同一个类只会被加载一次</li>
                        <li>建立了类加载的层次结构，提高了系统的安全性</li>
                    </ul>
                </div>
            </div>

            <!-- Question 2 -->
            <div class="mb-12 bg-white rounded-xl shadow-soft p-6">
                <h3 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
                    <span class="bg-indigo-600 text-white w-8 h-8 rounded-full flex items-center justify-center mr-3">2</span>
                    如何自定义ClassLoader？
                </h3>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        <span class="font-medium text-indigo-600">答：</span>自定义ClassLoader通常需要继承ClassLoader或URLClassLoader，并重写findClass方法：
                    </p>
                    
                    <div class="code-block p-4 rounded-lg mb-4 overflow-x-auto">
                        <pre><code class="text-sm language-java">public class MyClassLoader extends ClassLoader {
    private String classPath;
    
    public MyClassLoader(String classPath) {
        this.classPath = classPath;
    }
    
    @Override
    protected Class&lt;?&gt; findClass(String name) throws ClassNotFoundException {
        try {
            // 构建类文件的完整路径
            String fileName = classPath + File.separator + 
                              name.replace('.', File.separatorChar) + ".class";
            
            // 读取类文件
            try (FileInputStream fis = new FileInputStream(fileName);
                 ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
                
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = fis.read(buffer)) != -1) {
                    baos.write(buffer, 0, bytesRead);
                }
                byte[] classData = baos.toByteArray();
                
                // 将字节码转换为Class对象
                return defineClass(name, classData, 0, classData.length);
            }
        } catch (IOException e) {
            throw new ClassNotFoundException("Could not load class: " + name, e);
        }
    }
}</code></pre>
                    </div>
                    
                    <p class="text-gray-700">
                        如果需要打破双亲委派模型，则需要重写loadClass方法。
                    </p>
                </div>
            </div>

            <!-- Question 3 -->
            <div class="bg-white rounded-xl shadow-soft p-6">
                <h3 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
                    <span class="bg-indigo-600 text-white w-8 h-8 rounded-full flex items-center justify-center mr-3">3</span>
                    ClassLoader在Spring中的应用有哪些？
                </h3>
                <div class="pl-11">
                    <p class="mb-4 text-gray-700">
                        <span class="font-medium text-indigo-600">答：</span>Spring框架中ClassLoader的应用包括：
                    </p>
                    
                    <div class="grid md:grid-cols-2 gap-4 mb-4">
                        <div class="bg-indigo-50 p-4 rounded-lg">
                            <h4 class="font-medium text-indigo-600 mb-2">类路径扫描</h4>
                            <p class="text-gray-700">Spring使用ClassLoader加载类路径下的组件</p>
                            <div class="code-block p-2 rounded mt-2 overflow-x-auto">
                                <pre><code class="text-xs language-java">ClassPathScanningCandidateComponentProvider scanner = 
    new ClassPathScanningCandidateComponentProvider(true);
scanner.addIncludeFilter(new AnnotationTypeFilter(Component.class));
Set&lt;BeanDefinition&gt; candidates = scanner.findCandidateComponents("com.example");</code></pre>
                            </div>
                        </div>
                        
                        <div class="bg-indigo-50 p-4 rounded-lg">
                            <h4 class="font-medium text-indigo-600 mb-2">资源加载</h4>
                            <p class="text-gray-700">Spring的ResourceLoader使用ClassLoader加载资源</p>
                            <div class="code-block p-2 rounded mt-2 overflow-x-auto">
                                <pre><code class="text-xs language-java">ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource("classpath:config.xml");</code></pre>
                            </div>
                        </div>
                    </div>
                    
                    <ul class="list-disc pl-5 space-y-2 text-gray-700">
                        <li><strong>动态代理生成</strong>：Spring AOP使用ClassLoader加载动态生成的代理类</li>
                        <li><strong>Spring Boot的Fat JAR支持</strong>：使用自定义ClassLoader加载嵌套JAR中的类</li>
                        <li><strong>热部署支持</strong>：Spring Boot DevTools使用两个ClassLoader实现热部署</li>
                    </ul>
                </div>
            </div>
        </div>
    </div>

    <!-- Footer -->
    <footer class="bg-gray-900 text-white py-8">
        <div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
            <div class="flex flex-col md:flex-row justify-between items-center">
                <div class="mb-4 md:mb-0">
                    <h3 class="text-xl font-bold">技术小馆</h3>
                    <p class="text-gray-400 mt-1">深入技术细节，探索编程之美</p>
                </div>
                <div>
                    <a href="http://www.yuque.com/jtostring" class="text-gray-300 hover:text-white transition-colors" target="_blank">
                        <i class="fas fa-globe mr-2"></i> http://www.yuque.com/jtostring
                    </a>
                </div>
            </div>
            <div class="mt-8 pt-8 border-t border-gray-800 text-center text-gray-400 text-sm">
                &copy; 2023 技术小馆. 保留所有权利.
            </div>
        </div>
    </footer>

    <script>
        // Initialize Mermaid
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            },
            gantt: {
                axisFormat: '%H:%M'
            }
        });

        // Smooth scrolling for anchor links
        document.querySelectorAll('a[href^="#"]').forEach(anchor => {
            anchor.addEventListener('click', function (e) {
                e.preventDefault();
                document.querySelector(this.getAttribute('href')).scrollIntoView({
                    behavior: 'smooth'
                });
            });
        });
    </script>
</body>
</html>
```